<template>
  <el-dialog
    v-model="dialogVisible"
    :close-on-click-modal="false"
    class="datastore-operation-form"
    :title="opentionType"
    width="500px"
    draggable
  >
    <el-form
      ref="dataStoreFormRef"
      :model="datastoreForm"
      label-width="100px"
      style="max-width: 600px"
    >
      <el-form-item label="工作空间 :">
        <el-select
          v-model="datastoreForm.workspace"
          filterable
          :disabled="opentionType == '编辑'"
          placeholder="请选择工作空间"
        >
          <el-option
            v-for="workspaceItem in workspaceList"
            :key="workspaceItem.name"
            :label="workspaceItem.name"
            :value="workspaceItem.name"
          />
        </el-select>
      </el-form-item>
      <el-form-item
        label="数据源名称"
        prop="name"
        :rules="{
          required: true,
          message: '名称不能为空',
          trigger: 'blur',
        }"
      >
        <el-input v-model="datastoreForm.name" />
      </el-form-item>
      <el-form-item label="描述" prop="description">
        <el-input v-model="datastoreForm.description" />
      </el-form-item>
      <el-form-item
        label="数据源类型"
        prop="type"
        :rules="{
          required: true,
          message: '类型不能为空',
          trigger: 'blur',
        }"
      >
        <el-select
          v-model="datastoreForm.type"
          placeholder="请选择数据源类型..."
          style="width: 240px"
          @change="storeTypeChangeHandler"
        >
          <el-option-group
            v-for="group in storeTypeOptions"
            :key="group.label"
            :label="group.label"
          >
            <el-option
              v-for="item in group.options"
              :key="item.value"
              :label="item.label"
              :value="item.value"
            />
          </el-option-group>
        </el-select>
      </el-form-item>

      <template
        v-for="(parameterItem, parameterItemIndex) in datastoreForm.connectionParameters?.entry"
        :key="'parameterItemIndex' + parameterItemIndex"
      >
        <el-form-item
          v-if="parameterItem.needShow"
          :label="`${parameterItem.label}`"
          :prop="'connectionParameters.entry.' + parameterItemIndex + '.$'"
          :rules="{
            required: parameterItem.required,
            message: '参数不能为空',
            trigger: 'blur',
          }"
        >
          <el-select
            v-if="parameterItem.type == 'chartset'"
            v-model="parameterItem.$"
            filterable
            allow-create
            default-first-option
            :reserve-keyword="false"
            placeholder="选择字符编码"
          >
            <el-option v-for="item in commonEncodings" :key="item" :label="item" :value="item" />
          </el-select>
          <el-input
            v-else
            v-model="parameterItem.$"
            :type="parameterItem.type == 'password' ? 'password' : ''"
          >
            <template #suffix v-if="parameterItem.type == 'innerUrl'">
              <el-icon class="picker-folder" @click="pickFolder(parameterItem)"><Folder /></el-icon>
            </template>
          </el-input>
        </el-form-item>
      </template>

      <el-form-item
          v-if="Object.keys(datastoreForm).includes('url')"
          :label="`url`"
          prop="url"
          :rules="{
            required: true,
            message: '参数不能为空',
            trigger: 'blur',
          }"
        >
          <el-input
            v-model="datastoreForm.url"
          >
            <template #suffix>
              <el-icon class="picker-folder" @click="pickFolder()"><Folder /></el-icon>
            </template>
          </el-input>
        </el-form-item>
    </el-form>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="closeDialog">取消</el-button>
        <el-button type="primary" @click="addOrUpdate">确认</el-button>
      </span>
    </template>
  </el-dialog>
  <folderPicker
    v-model:visible="folderPickerVisible"
    :pick-type="folderPickerType"
    @picked="setPickerUrl"
  ></folderPicker>
</template>

<script setup lang="ts">
import { ref, reactive, onBeforeMount } from 'vue'
import { ElMessage, type FormInstance } from 'element-plus'
import useWorkspaceModal from '@/composables/useWorkspace'
import type { IDatastore } from 'geoserver-helper/interface'
import { restHelperInstance } from '@/composables/useGeoHelper'
import { Folder } from '@element-plus/icons-vue'
import folderPicker from './folderPicker.vue'
import { DICTIONARY } from '@/config/dictionary'

const commonEncodings = DICTIONARY.commonEncodings

const workspaceModal = useWorkspaceModal()
// 表单ref
const dataStoreFormRef = ref<FormInstance>()
const dialogVisible = ref(false)
//文件资源路径选择器显隐
const folderPickerVisible = ref(false)
//文件资源路径选择类型
const folderPickerType = ref<'' | 'Folder' | 'File'>('')
const opentionType = ref('新增')
const workspaceList = workspaceModal.workspaceList
//TODO 栅格类型 后期需要和IDatastore 同步
const coverageTypes = ["GeoTIFF", "ImageMosaic", "MBTiles", "ArcGrid", "WorldImage"]


//矢量数据源连接参数库
const connectionDictionary: {
  [k in IDatastore.VectorDatastoreType]: IDatastore.ConnectionRecord[]
} = {
  ["PostGIS"]: [
    { '@key': 'host', $: 'localhost', label: '服务器', required: true, needShow: true },
    { '@key': 'port', $: '5432', label: '端口', required: false, needShow: true },
    { '@key': 'database', $: '', label: '库', required: true, needShow: true },
    { '@key': 'user', $: 'postgres', label: '用户', required: true, needShow: true },
    {
      '@key': 'passwd',
      $: 'postgres',
      label: '密码',
      required: true,
      needShow: true,
      type: 'password',
    },
    { '@key': 'dbtype', $: 'postgis', label: '数据库类型', required: true, needShow: false },
  ],
  ["Mysql"]: [
    { '@key': 'host', $: 'localhost', label: '服务器', required: true, needShow: true },
    { '@key': 'port', $: '3306', label: '端口', required: false, needShow: true },
    { '@key': 'database', $: '', label: '库', required: true, needShow: true },
    { '@key': 'user', $: 'root', label: '用户', required: true, needShow: true },
    { '@key': 'passwd', $: '', label: '密码', required: true, needShow: true, type: 'password' },
    { '@key': 'dbtype', $: 'mysql', label: '数据库类型', required: true, needShow: false },
  ],
  ["GeoPackage"]: [
    { '@key': 'database', $: '', label: '库', required: true, needShow: true, type: 'innerUrl' },
    { '@key': 'dbtype', $: 'geopkg', label: '数据库类型', required: true, needShow: false },
  ],
  ["Shapefile"]: [
    { '@key': 'url', $: '', label: '路径', required: true, needShow: true, type: 'innerUrl' },
    { '@key': 'charset', $: 'ISO-8859-1', label: '编码', required: true, needShow: true, type: 'chartset' },
  ],
  ["Directory of spatial files (shapefiles)"]: [
    { '@key': 'url', $: '', label: '路径', required: true, needShow: true, type: 'innerUrl' },
    {
      '@key': 'charset',
      $: 'ISO-8859-1',
      label: '编码',
      required: true,
      needShow: true,
      type: 'chartset',
    },
  ],
}
const datastoreForm = reactive<IDatastore.DatastoreOperationForm>({
  workspace: '',
  description: '',
  name: '',
  type: 'Shapefile' as IDatastore.DatastoreType,
  connectionParameters: {
    entry: connectionDictionary['Shapefile'],
  },
  enabled: true,
})
//数据源的选择下拉框
const storeTypeOptions = [
  {
    label: '矢量',
    options: [
      {
        value: 'Shapefile',
        label: 'Shapefile',
      },
      {
        value: 'Directory of spatial files (shapefiles)',
        label: 'Shapefiles目录',
      },
      {
        value: 'PostGIS',
        label: 'PostGIS',
      },
      {
        value: 'MySql',
        label: 'MySql',
      },
      {
        value: 'GeoPackage',
        label: 'GeoPackage',
      }
    ],
  },
  {
    label: '栅格',
    options: [
      {
        value: 'GeoTIFF',
        label: 'GeoTIFF',
      },
      {
        value: 'ImageMosaic',
        label: 'ImageMosaic',
      },
      {
        value: 'MBTiles',
        label: 'MBTiles',
      },
      {
        value: 'ArcGrid',
        label: 'ArcGrid',
      },
      {
        value: 'WorldImage',
        label: 'WorldImage',
      },
    ],
  },
]
let orignDatastore = reactive<IDatastore.DatastoreInfo | IDatastore.CoveragestoreInfo>({
  name: '',
  type: '',
  dateCreated: '',
  connectionParameters: {
    entry: [],
  },
  url:'',
  enabled: false,
  dateModified: '',
  _default: false,
  disableOnConnFailure: false,
  featureTypes: '',
  workspace: {
    name: '',
    href: '',
  },
})
//当前要选择路径的项
const currentPickerItem = ref<IDatastore.ConnectionRecord>()

/**
 * @description: 数据源类型改变事件
 * @param {*} selectedValue
 * @return {*}
 */
const storeTypeChangeHandler = (selectedValue: IDatastore.DatastoreType) => {
  if(coverageTypes.includes(selectedValue)){
    datastoreForm.connectionParameters = undefined
    datastoreForm.url = ''
  }else {
    if (datastoreForm.connectionParameters) {
      datastoreForm.connectionParameters.entry = [...connectionDictionary[selectedValue as IDatastore.VectorDatastoreType]]
    }else {
      datastoreForm.connectionParameters = {
        entry: [...connectionDictionary[selectedValue as IDatastore.VectorDatastoreType]],
      }
    }
    if(Object.hasOwnProperty.call(datastoreForm, "url")){
      delete datastoreForm.url
    }
  }
}

/**
 * @description: 选择文件或者文件夹
 * @param {*} inputInfo
 * @return {*}
 */
const pickFolder = (inputInfo?: IDatastore.ConnectionRecord) => {
  if(inputInfo){
    currentPickerItem.value = inputInfo
  }else {
    currentPickerItem.value = undefined
  }
  const folderTypes = ['Directory of spatial files (shapefiles)']
  if (folderTypes.includes(datastoreForm.type as string)) {
    folderPickerType.value = 'Folder'
  } else {
    folderPickerType.value = 'File'
  }
  folderPickerVisible.value = true
}

/**
 * @description: 设置拾取的url
 * @param {*} url
 * @return {*}
 */
const setPickerUrl = (url: string) => {
  if (currentPickerItem.value) {
    currentPickerItem.value.$ = url
  }else {
    datastoreForm.url = url
  }
}

// openDialog
const openDialog = (opentionTypeParam?: string) => {
  if (opentionTypeParam) {
    opentionType.value = opentionTypeParam
  }
  dialogVisible.value = true
}
const setOrignDatastore = (orignDatastoreParam: IDatastore.DatastoreInfo | IDatastore.CoveragestoreInfo) => {
  orignDatastore = orignDatastoreParam
  datastoreForm.workspace = orignDatastoreParam.workspace.name
  datastoreForm.name = orignDatastoreParam.name
  // datastoreForm.type = orignDatastoreParam.type
  storeTypeChangeHandler(orignDatastoreParam.type as IDatastore.DatastoreType)
  if ((orignDatastoreParam as IDatastore.DatastoreInfo).connectionParameters) {
    const currentOrignDatastoreParam = orignDatastoreParam as IDatastore.DatastoreInfo
    currentOrignDatastoreParam.connectionParameters?.entry.forEach((singleEntry) => {
      if (datastoreForm.connectionParameters) {
        const current = datastoreForm.connectionParameters.entry.find((findItem) => {
          return findItem['@key'] == singleEntry['@key']
        })
        if (current) {
          current.$ = singleEntry.$
        }
      }
    })
  }else {
    const currentOrignDatastoreParam = orignDatastoreParam as IDatastore.CoveragestoreInfo
    datastoreForm.url = currentOrignDatastoreParam.url
  }
  // workspaceForm.default = false
  // workspaceForm.name = orignWorkspaceParam.name + ''
}

const closeDialog = () => {
  datastoreForm.workspace = ''
  datastoreForm.description = ''
  datastoreForm.name = ''
  // datastoreForm.type = ''
  if (datastoreForm.connectionParameters) {
    datastoreForm.connectionParameters.entry = []
  }
  dialogVisible.value = false
}
interface updateDatastoreEmit {
  (e: 'updateDatastore'): void
}
const emit = defineEmits<updateDatastoreEmit>()
const addOrUpdate = () => {
  dataStoreFormRef.value?.validate(async (valid) => {
    if (valid) {
      if (opentionType.value == '新增') {
        if(coverageTypes.includes(datastoreForm.type as string)){
          restHelperInstance.addCoverageDatastoreApi(datastoreForm)
          .then(() => {
            ElMessage({
              type: 'success',
              message: '添加成功',
            })
            closeDialog()
            emit('updateDatastore')
          })
          .catch(() => {
            ElMessage({
              type: 'error',
              message: '添加失败！请检查数据存储名称名称是否符合要求',
            })
          })
        }else {
          restHelperInstance
          .addDatastoreApi(datastoreForm)
          .then(() => {
            ElMessage({
              type: 'success',
              message: '添加成功',
            })
            closeDialog()
            emit('updateDatastore')
          })
          .catch(() => {
            ElMessage({
              type: 'error',
              message: '添加失败！请检查数据存储名称名称是否符合要求',
            })
          })
        }
      } else if (opentionType.value == '编辑') {
        if(coverageTypes.includes(datastoreForm.type as string)){
          restHelperInstance
          .updateCoverageDatastoreApi(orignDatastore as IDatastore.DatastoreInfo, datastoreForm)
          .then(() => {
            ElMessage({
              type: 'success',
              message: '更新成功',
            })
            closeDialog()
            emit('updateDatastore')
          })
          .catch(() => {
            ElMessage({
              type: 'error',
              message: '更新失败！请检查工作空间是否允许删除',
            })
          })
        }else {
          restHelperInstance
          .updateDatastoreApi(orignDatastore as IDatastore.DatastoreInfo, datastoreForm)
          .then(() => {
            ElMessage({
              type: 'success',
              message: '更新成功',
            })
            closeDialog()
            emit('updateDatastore')
          })
          .catch(() => {
            ElMessage({
              type: 'error',
              message: '更新失败！请检查工作空间是否允许删除',
            })
          })
        }

      }
    }
  })
}
onBeforeMount(() => {
  // 此处执行一次后确保 workspaceList 有值
  workspaceModal.getWorkspaceList()
  workspaceModal.getDefaultWorkspace().then(() => {
    datastoreForm.workspace = workspaceModal.defaultWorkspace.value.name
  })
})

defineExpose({ openDialog, setOrignDatastore })
</script>

<style lang="scss">
.datastore-operation-form {
  .el-dialog__body {
    padding: 20px;
    .el-form {
      .el-input {
        .picker-folder {
          cursor: pointer;
        }
      }
    }
  }
  .el-dialog__footer {
    padding: 20px;
    text-align: center;
  }
}
</style>
